use re 'eval';
use Dumpvalue;
package EnhancedRe;
my @comments;
$dumper = Dumpvalue->new;
use vars qw(%pairRe);
sub getPairRe
{
	return qq{
	( # paren group 2 (parens)
	$_[0]
		( # paren group 3 (contents of parens)
			(?:
				(?> [^$_[0]$_[1]]+ ) # Non-parens without backtracking
				|
				(?-2) # Recurse to start of paren group 2
			)*
		)
	$_[1]
	)
	};
}
my %pairs = ('('=>')', '['=>']', '{'=>'}');
%pairRe = map { $_ => getPairRe("\\$_","\\$pairs{$_}") } keys %pairs;
sub _join_re
{
    my $val = shift;
    return $val unless ref $val;
    my $b = not length($val->{type});
    return '(?:'.($b?'(?{ pos() < $pos and (pop(@{$stack->[0]}), shift(@stack), 1) and print "we back!\n" or unshift @stack, [] and print "try it!pos=$pos\n"; $pos = pos; })':'')."($val->{type}".(join '', map { _join_re($_) } @{$val->{content}}).')'.($b?'(?{ $pos = pos(); local $res = shift @stack; push @{$stack[0]}, grep { not ref $_ or scalar(@$_) } $^N, $res ; print "stack is $#stack, capture is $^N\n"; })':'').")$val->{repeat}";
}
sub new
{
    my ($class, $re) = @_;
    #$re =~ s/\s*(?:#.*)?\n//g;
    #print "re without comments: $re\n";
    $re =~ s/\\/\\\\/g;
    $re =~ s/(?<!\\\\)\((\?[[:punct:]mgxi])?/',{type=>'$1',content=>['/mg;
    $re =~ s/(?<!\\\\)\)(?<REPEAT>
                (?:                       #repeat modifiers
                    [*+?]               #* or +
                    |
                    \{\d*(?:,\d*)?\}    #{m, n}
                )
                \??                     #greedy? 
            )?/'],repeat=>'$1'},'/mgx;
    print "re as array: $re\n";
    $re = eval("{content=>['$re']}");
    $dumper->dumpValue($re);
    $re = _join_re($re);
    print "re joined: $re\n;";

#    $re =~ s/\(                         #start parens
#                (   
#                   (?:                  
#                        (?!\?)         #exclude non-capturing groups
#                        |
#                        (?=\?<\w+>)    #but include named-groups
#                   )
#                    (?:                 
#                        [^()]+          #any symbol except parens
#                        |
#                        $pairRe{'('}    #paren group
#                    )*
#                )
#            \)
#            (?<REPEAT>
#                (?:                     #repeat modifiers
#                    [*+?]                #* or +
#                    |
#                    \{\d*(?:,\d*)?\}    #{m, n}
#                )
#                \??                     #greedy? 
#            )?
#            /(?:(?{ pos() < \$pos && print 'we back!'; \$pos = pos; })(?:$1(?{ \$pos = pos(); print "capture is \$^N\n"; })))/mgx;
    my $self = qr/$re/;
    return bless $self, $class;
}
sub exec($$@)
{
    my ($self, $str, @flags) = @_;
    my $f = join '', @flags;
    my $c = [];
    @stack = ([]);
    my $pos = 0;
    my $res;
    eval "while(\$str =~ /\$self/$f) {;}";
    return [grep { not ref $_ or scalar(@$_) } @stack];
}
package main;
use Dumpvalue;
$dumper = Dumpvalue->new;
my %literals = ('"'=>{name=>'string', values=>[]}, "'"=>{name=>'char', values=>[]});
my %pairRe = %EnhancedRe::pairRe;

my $typeRe = qr/
	(
		([*]*)(const|volatile)?([*]*|\s)
		(
			\w+
			|
			\((?-5)\)
		)
		($pairRe{'['})?
	)
/xm;
my $declRe = qr{(\w+\s)*               #TYPE MODIFIERS
                \w+                    #TYPE
                (?:\s|(?=[*]))         #SEPARATOR
                $typeRe}mx;
my $funcRe = qr/
	$declRe(?:\s+|(?<=[*]))
		\(
			(?<ARGLIST>
			(?:$declRe,)*$declRe
			)
		\)
		(
			\{
				(?<BODY>
					(?:[^{}]|(?-2))*
				)
			\}
		)
	/mx;
sub saveComment($)
{
	my $comment = shift;
	push @comments, $comment;
	return $#comments;
}
sub saveLiteral($$)
{
	my ($char, $text) = @_;
	push @{$literals{$char}{values}}, $text;
	return "$literals{$char}{name}$#{$literals{$char}{values}}";
}
sub exclude
{
	my $char = shift;
	return "[^$char]";
}
sub C_Translate
{
	my($source, $dest) = @_;
	open(in, "<$source");
	my @lines = <in>;
	my $src = join("\n", @lines);
	close(in);
	my $out = STDOUT;
	if($dest)
	{
		open($out, ">$dest");
	}
	$src =~ s'//.*?$|/\*.*?\*/'"/*comment".saveComment($0)."*/"'mge;
	#my $literalRe = q#(["'])((??{exclude($1)})*\\.)*(??{exclude($1)})*(??{$1})#;
	my ($char, $ex);
	my $literalRe = q#(["'])(?{ $char=$^N; $ex="[^$^N]"; })((??{$ex})*\\\\.)*(??{ $ex })*(??{  $char })#;
	$src =~ s{$literalRe}{saveLiteral $1, $0}mge;
	$src =~ s/(?<=[[:punct:]])\s+(?=[[:punct:][:alnum:]])|(?<=\w)\s+(?=[[:punct:]])//g;
	my @cond = $src =~ /((if|while)$pairRe{'('}(?<BLOCK>[^{};]*;))/mgx;
	$src =~ s/(if|while)$pairRe{'('}(?<BLOCK>[^{};]*;)/$1$2\{$+{BLOCK}}/mgx;
	print $out "----------CONDITIONAL-----------\n";
	print $out join("\n", @cond)."\n";
	print $out "----------DECLARATIONS----------\n";
    my $declEnRe = EnhancedRe->new("(?:(?<=[{;}])|(?<=[*]/)|^)($declRe)(?=[;=])");
    while($src =~ m#(?:(?<=[{;}])|(?<=[*]/)|^)($declEnRe)(?=[;=])#mg)
    {
        print $out "$1\n";
    }
    #print $out "Declaration re: $declEnRe\n";
    #print $out join("\n", @declarations);
    $dumper->dumpValue($declEnRe->exec($src, 'mgx'));
	my @parens = $src =~ m/$pairRe{'('}/mgx;
	#print $out join(', ', %pairRe);
	print $out "----------PARENTHESES-----------\n";

	print $out join("\n", @parens)."\n";
	print $out "----------SOURCE----------------\n";
	print $out $src;
}
C_Translate @ARGV;

